package com.kxmall.framework.monitor;

import cn.dev33.satoken.stp.StpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Token唯一性监控器
 * 监控Token生成、使用和唯一性情况
 *
 * @author kxmall
 */
@Slf4j
@Component
public class TokenUniquenessMonitor {

    // 监控统计
    private final AtomicLong totalTokenGenerated = new AtomicLong(0);
    private final AtomicLong appTokenCount = new AtomicLong(0);
    private final AtomicLong riderTokenCount = new AtomicLong(0);
    private final AtomicLong sysTokenCount = new AtomicLong(0);
    private final AtomicLong duplicateTokenDetected = new AtomicLong(0);
    private final AtomicLong tokenValidationFailures = new AtomicLong(0);

    // Token记录表（用于检测重复和监控）
    private final ConcurrentHashMap<String, TokenRecord> activeTokens = new ConcurrentHashMap<>();

    /**
     * 记录Token生成
     */
    public void recordTokenGeneration(String tokenValue, String loginId, String userType, String deviceType, Long userId) {
        try {
            // 检查Token是否已存在（理论上不应该存在）
            if (activeTokens.containsKey(tokenValue)) {
                duplicateTokenDetected.incrementAndGet();
                log.error("🚨 检测到重复Token - Token前缀: {}, 用户: {}, 设备: {}", 
                    tokenValue.substring(0, Math.min(10, tokenValue.length())) + "...", loginId, deviceType);
            }

            // 记录新Token
            TokenRecord record = new TokenRecord(tokenValue, loginId, userType, deviceType, userId, System.currentTimeMillis());
            activeTokens.put(tokenValue, record);
            
            // 更新统计
            totalTokenGenerated.incrementAndGet();
            updateUserTypeCount(userType, 1);

            log.info("🔑 Token生成监控 - 用户类型: {}, 设备: {}, 用户ID: {}, Token前缀: {}, 总数: {}", 
                userType, deviceType, userId, 
                tokenValue.substring(0, Math.min(10, tokenValue.length())) + "...",
                totalTokenGenerated.get());

        } catch (Exception e) {
            log.error("记录Token生成异常", e);
        }
    }

    /**
     * 记录Token验证失败
     */
    public void recordTokenValidationFailure(String reason, String tokenPrefix, String loginId) {
        try {
            tokenValidationFailures.incrementAndGet();
            log.warn("🚨 Token验证失败 - 原因: {}, Token前缀: {}, 用户: {}, 累计失败: {}", 
                reason, tokenPrefix, loginId, tokenValidationFailures.get());
        } catch (Exception e) {
            log.error("记录Token验证失败异常", e);
        }
    }

    /**
     * 记录Token使用
     */
    public void recordTokenUsage(String tokenValue, String operation) {
        try {
            TokenRecord record = activeTokens.get(tokenValue);
            if (record != null) {
                record.updateLastUsed();
                log.debug("Token使用记录 - 操作: {}, Token前缀: {}, 用户: {}", 
                    operation, 
                    tokenValue.substring(0, Math.min(10, tokenValue.length())) + "...",
                    record.getLoginId());
            }
        } catch (Exception e) {
            log.error("记录Token使用异常", e);
        }
    }

    /**
     * 检查Token唯一性
     */
    public boolean checkTokenUniqueness(String tokenValue) {
        try {
            // 检查Token是否在活跃列表中
            boolean exists = activeTokens.containsKey(tokenValue);
            
            if (!exists) {
                log.debug("Token唯一性检查 - Token不在活跃列表中: {}", 
                    tokenValue.substring(0, Math.min(10, tokenValue.length())) + "...");
            }
            
            return !exists; // 不存在表示唯一
        } catch (Exception e) {
            log.error("检查Token唯一性异常", e);
            return true; // 异常时假设唯一
        }
    }

    /**
     * 获取用户Token数量
     */
    public int getUserTokenCount(String loginId, String deviceType) {
        try {
            return (int) activeTokens.values().stream()
                .filter(record -> loginId.equals(record.getLoginId()) && deviceType.equals(record.getDeviceType()))
                .count();
        } catch (Exception e) {
            log.error("获取用户Token数量异常", e);
            return 0;
        }
    }

    /**
     * 清理过期Token记录
     */
    @Scheduled(fixedRate = 300000) // 5分钟执行一次
    public void cleanupExpiredTokens() {
        try {
            long currentTime = System.currentTimeMillis();
            long expireTime = 8640000 * 1000; // 1天过期时间
            
            int beforeSize = activeTokens.size();
            
            activeTokens.entrySet().removeIf(entry -> {
                TokenRecord record = entry.getValue();
                boolean expired = (currentTime - record.getCreateTime()) > expireTime;
                
                if (expired) {
                    // 更新用户类型统计
                    updateUserTypeCount(record.getUserType(), -1);
                }
                
                return expired;
            });
            
            int afterSize = activeTokens.size();
            int cleanedCount = beforeSize - afterSize;
            
            if (cleanedCount > 0) {
                log.info("Token记录清理完成 - 清理数量: {}, 剩余活跃Token: {}", cleanedCount, afterSize);
            }
            
        } catch (Exception e) {
            log.error("清理过期Token记录异常", e);
        }
    }

    /**
     * 获取监控统计信息
     */
    public String getMonitoringStats() {
        return String.format(
            "Token唯一性监控统计 - 总生成: %d, APP: %d, 骑手: %d, 系统: %d, 重复检测: %d, 验证失败: %d, 活跃Token: %d",
            totalTokenGenerated.get(), appTokenCount.get(), riderTokenCount.get(), sysTokenCount.get(),
            duplicateTokenDetected.get(), tokenValidationFailures.get(), activeTokens.size()
        );
    }

    /**
     * 获取详细统计信息
     */
    public TokenStats getDetailedStats() {
        return new TokenStats(
            totalTokenGenerated.get(),
            appTokenCount.get(),
            riderTokenCount.get(),
            sysTokenCount.get(),
            duplicateTokenDetected.get(),
            tokenValidationFailures.get(),
            activeTokens.size()
        );
    }

    /**
     * 重置统计信息
     */
    public void resetStats() {
        totalTokenGenerated.set(0);
        appTokenCount.set(0);
        riderTokenCount.set(0);
        sysTokenCount.set(0);
        duplicateTokenDetected.set(0);
        tokenValidationFailures.set(0);
        activeTokens.clear();
        log.info("Token唯一性监控统计已重置");
    }

    /**
     * 检查是否存在问题
     */
    public boolean hasIssues() {
        return duplicateTokenDetected.get() > 0 || tokenValidationFailures.get() > 10;
    }

    /**
     * 更新用户类型统计
     */
    private void updateUserTypeCount(String userType, int delta) {
        switch (userType) {
            case "app_user":
                appTokenCount.addAndGet(delta);
                break;
            case "rider_user":
                riderTokenCount.addAndGet(delta);
                break;
            case "sys_user":
                sysTokenCount.addAndGet(delta);
                break;
        }
    }

    /**
     * Token记录类
     */
    public static class TokenRecord {
        private final String tokenValue;
        private final String loginId;
        private final String userType;
        private final String deviceType;
        private final Long userId;
        private final long createTime;
        private volatile long lastUsed;

        public TokenRecord(String tokenValue, String loginId, String userType, String deviceType, Long userId, long createTime) {
            this.tokenValue = tokenValue;
            this.loginId = loginId;
            this.userType = userType;
            this.deviceType = deviceType;
            this.userId = userId;
            this.createTime = createTime;
            this.lastUsed = createTime;
        }

        public void updateLastUsed() {
            this.lastUsed = System.currentTimeMillis();
        }

        // Getters
        public String getTokenValue() { return tokenValue; }
        public String getLoginId() { return loginId; }
        public String getUserType() { return userType; }
        public String getDeviceType() { return deviceType; }
        public Long getUserId() { return userId; }
        public long getCreateTime() { return createTime; }
        public long getLastUsed() { return lastUsed; }
    }

    /**
     * Token统计信息类
     */
    public static class TokenStats {
        private final long totalGenerated;
        private final long appTokens;
        private final long riderTokens;
        private final long sysTokens;
        private final long duplicateDetected;
        private final long validationFailures;
        private final int activeTokens;

        public TokenStats(long totalGenerated, long appTokens, long riderTokens, long sysTokens, 
                         long duplicateDetected, long validationFailures, int activeTokens) {
            this.totalGenerated = totalGenerated;
            this.appTokens = appTokens;
            this.riderTokens = riderTokens;
            this.sysTokens = sysTokens;
            this.duplicateDetected = duplicateDetected;
            this.validationFailures = validationFailures;
            this.activeTokens = activeTokens;
        }

        // Getters
        public long getTotalGenerated() { return totalGenerated; }
        public long getAppTokens() { return appTokens; }
        public long getRiderTokens() { return riderTokens; }
        public long getSysTokens() { return sysTokens; }
        public long getDuplicateDetected() { return duplicateDetected; }
        public long getValidationFailures() { return validationFailures; }
        public int getActiveTokens() { return activeTokens; }
    }
}
